package site.sorghum.ddl.extra;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;

public class ClassUtil {

    /**
     * 获取所有字段（包括父类的字段）
     *
     * @param tClass 类名
     * @return 所有字段列表
     */
    public static List<Field> fetchAllFields(Class<?> tClass) {
        List<Field> fields = new ArrayList<>();
        Class<?> clazz = tClass;
        while (clazz != null) {
            Field[] fieldArray = clazz.getDeclaredFields();
            fields.addAll(Arrays.asList(fieldArray));
            clazz = clazz.getSuperclass();
        }
        return fields;
    }

    public static Class<?>[] fetchAllInterfaces(Class<?> tClass) {
        List<Class<?>> interfaces = new ArrayList<>();
        Class<?> clazz = tClass;
        while (clazz != null) {
            Class<?>[] interfacesArray = clazz.getInterfaces();
            interfaces.addAll(Arrays.asList(interfacesArray));
            clazz = clazz.getSuperclass();
        }
        return interfaces.toArray(new Class<?>[0]);
    }

    /**
     * 扫描指定包名下的所有类
     *
     * @param packageName 要扫描的包名
     * @return 包下所有类的Class对象列表
     * @throws IOException            如果读取类文件时发生错误
     * @throws ClassNotFoundException 如果类无法加载
     */
    public static List<Class<?>> scanPackage(String packageName)
            throws IOException, ClassNotFoundException {
        List<Class<?>> classes = new ArrayList<>();
        String path = packageName.replace('.', '/');
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        Enumeration<URL> resources = classLoader.getResources(path);

        while (resources.hasMoreElements()) {
            URL resource = resources.nextElement();
            if (resource.getProtocol().equals("file")) {
                File directory = new File(resource.getFile());
                if (directory.exists()) {
                    scanDirectory(packageName, directory, classes);
                }
            }
        }
        return classes;
    }

    /**
     * 递归扫描目录中的类文件
     *
     * @param packageName 当前包名
     * @param directory   当前目录
     * @param classes     类列表收集器
     * @throws ClassNotFoundException 如果类无法加载
     */
    private static void scanDirectory(String packageName, File directory, List<Class<?>> classes)
            throws ClassNotFoundException {
        File[] files = directory.listFiles();
        if (files == null) {
            return;
        }

        for (File file : files) {
            if (file.isDirectory()) {
                scanDirectory(packageName + "." + file.getName(), file, classes);
            } else if (file.getName().endsWith(".class")) {
                String className = packageName + '.' + file.getName().substring(0, file.getName().length() - 6);
                classes.add(Class.forName(className));
            }
        }
    }
}